package com.shao.demo.apigetway.filter;

import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;

/**
 * @author zhiqi.shao
 * @Date 2018/5/24 16:02
 */
@Slf4j
public class AccessFilter extends ZuulFilter {

    /**
     * flterType: 过滤器的类型， 它决定过滤器在请求的哪个生命周期中执行。这里
     * 定义为pre, 代表会在请求被路由之前执行。
     *
     * @return
     */
    @Override
    public String filterType() {
        return "pre";
    }

    /**
     * flterOrder: 过滤器的执行顺序。当请求在一个阶段中存在多个过滤器时， 需
     * 要根据该方法返回的值来依次执行。
     */
    @Override
    public int filterOrder() {
        return 0;
    }

    /**
     * shouldFlter: 判断该过滤器是否需要被执行。这里我们直接返回了true, 因
     * 此该过滤器对所有请求都会生效。实际运用中我们可以利用该函数来指定过滤器的
     * 有效范围。
     *
     * @return
     */
    @Override
    public boolean shouldFilter() {
        return true;
    }

    /**
     * run: 过滤器的具体逻辑。这里我们通过ctx.setSendZuulResponse(false)
     * 令zuul过滤该请求，不对其进行路由,然后通过ctx.setResponseStatusCode
     * (401)设置了其返回的错误码， 当然也可以进一步优化我们的返回， 比如，通
     * 过ctx.setResponseBody(body)对返回的body内容进行编辑等。
     *
     * @return
     */
    @Override
    public Object run()  {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        log.info("send {} request to{}", request.getMethod(), request.getRequestURL().toString());
        Object accessToken = request.getParameter("accessToken");
        if (accessToken == null) {
            log.warn("access token is empty");
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
        }
        log.info("accessToken ok");
        // todo 这里没有拿到taceID,但是下游服务 feign在controller里可以拿到 ,问题待解决
        log.info("trace Id:{} spanId:{}",request.getHeader("X-B3-Traceid"),request.getHeader("X-B3-Spanid"));
        return null;
    }

}
